<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.4"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Flow-IPC: Structured Message Transport</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectalign">
   <div id="projectname">Flow-IPC<span id="projectnumber">&#160;2.0.0</span>
   </div>
   <div id="projectbrief">Flow-IPC project: Full implementation reference.</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.4 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

</div><!-- top -->
<div><div class="header">
  <div class="headertitle"><div class="title">Structured Message Transport </div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><center><b>MANUAL NAVIGATION:</b> <a class="el" href="universes.html">Preceding Page</a> - <a class="el" href="chan_struct_advanced.html">Next Page</a> - <a href="./pages.html"><b>Table of Contents</b></a> - <a class="el" href="namespaceipc.html"><b>Reference</b></a></center><hr  />
<p >This page explains how to send and receive structured messages, including requests, over a channel &ndash; for many users the essential purpose of the library. (Or go back to preceding page: <a class="el" href="universes.html">Multi-split Universes</a>. <a class="el" href="chan_open.html">Sessions: Opening Channels</a> would also be a natural immediate pre-requisite for the current page.)</p>
<h2>Context: Channels </h2>
<p >To restate from <a class="el" href="chan_open.html">Sessions: Opening Channels</a> &ndash; a <b>channel</b> is a <em>bundling</em> of the peer resources required for, essentially, a bidirectional pipe capable of transmitting binary messages (<b>blobs</b>) and, optionally, native handles. A particular <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">ipc::transport::Channel</a> (as specified at compile-time via its template parameters) may, for example, consist of an outgoing POSIX MQ handle and a similar incoming-MQ handle; or conceptually similar SHM-backed MQs (boost.ipc MQs). A peer <a class="el" href="classipc_1_1transport_1_1Channel.html">Channel</a> can be <b>upgraded</b> to an <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">ipc::transport::struc::Channel</a> (or <code>sync_io</code>-pattern counterpart, <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">ipc::transport::struc::sync_io::Channel</a>) in order to represent a structured, arbitrarily-sized datum per message as opposed to a mere (limited-size) blob.</p>
<p >Put more abstractly, however, a channel is, well, a channel of reliable bidirectional messaging. That said, if one takes a look at its API &ndash; knowing nothing else &ndash; it will be obvious it transmits:</p><ul>
<li>binary <b>blobs</b>; and</li>
<li>(optionally) native <b>handles</b> (FDs in POSIX/Unix/Linux parlance).</li>
</ul>
<p >Each message contains either exactly one blob (whose size is limited by the compile-time-chosen low-level transport), exactly one native handle, or both.</p>
<p >Handles aside, typically it is not convenient to manually represent logical data as binary blobs. The size is limited and transport-dependent for one; but that aside it is simply inconvenient and potentially slow to pack data in this fashion. For this reason <b>serialization frameworks</b> exist, and we certainly had no desire to reinvent the wheel. We simply chose the best one &ndash; <a href="https://capnproto.org">capnp (Cap'n Proto)</a> &ndash; and built around its API. The result is: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">ipc::transport::struc::Channel</a> (and/or its <code>sync_io</code> counterpart <code>struc::sync_io::Channel</code>).</p>
<p >The steps to work with a <code>struc::Channel</code> are as follows.</p><ol type="1">
<li>Open an <em>unstructured</em> <code>Channel</code>. This is explained in-depth in <a class="el" href="chan_open.html">Sessions: Opening Channels</a>. (One can also open a channel manually without <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a>. We will discuss this, typically advanced or optional ability, in later pages of this Manual.) The result shall be an object whose type is an instance of <a class="el" href="classipc_1_1transport_1_1Channel.html" title="Peer to a bundle of 1-2 full-duplex pipe(s), one for transmitting unstructured binary blobs; the othe...">ipc::transport::Channel</a> class template, or possibly a sub-class thereof. (In the latter case the sub-class adds <em>no</em> data on top of the <code>Channel</code> &ndash; only a small convenience API whose significance is low in our context here.)</li>
<li>Without directly using this <code>Channel</code>, <em>upgrade</em> it to a <code>struc::Channel</code> object. This is done via C++ move semantics: The new <code>struc::Channel</code> constructor takes a <code>Channel&amp;&amp;</code> reference, thus taking over the guts of the unstructured <code>Channel</code>, while the original <code>Channel</code> object becomes blank &ndash; as-if default-constructed.</li>
<li>Use the new <code>struc::Channel</code>.<ul>
<li>The subsumed unstructured <code>Channel</code> is still available for limited needs, most notably <a class="el" href="classipc_1_1transport_1_1Channel.html#a290395d720167759bfa1eda1e86bf123" title="Performs hndl_snd()-&gt; and/or blob_snd()-&gt; same method, returning true if all (1-2) invoked methods re...">ipc::transport::Channel::auto_ping()</a> and <a class="el" href="classipc_1_1transport_1_1Channel.html#abf25364b49b9fdd3ba4b1541b3a50356" title="Performs hndl_rcv()-&gt; and/or blob_rcv()-&gt; same method, returning true if all (1-2) invoked methods re...">ipc::transport::Channel::idle_timer_run()</a>.</li>
<li>However, in the main, one uses the <code>struc::Channel</code> API directly, exclusively.</li>
</ul>
</li>
<li>When done with it, destroy it.</li>
</ol>
<p >Each side of the conversation follows the above procedure.</p>
<p >Let's discuss step 2 of this procedure: upgrading a <code>Channel</code> to <code>struc::Channel</code>.</p>
<h2>Upgrading <code>Channel</code> to <code>struc::Channel</code> </h2>
<p >By the time you've got your unstructured <code>Channel</code>, you'd already made decisions as to its underlying low-level transport(s). (If you used <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a>, as recommended, you did this using the template knobs of <code>Session_server</code> and <code>Client_session</code>.) These details, roughly speaking, will not matter when using the upgraded <code>struc::Channel</code>. There are only a couple of things you must ensure about the underlying transports:</p><ul>
<li>If you intend to ever transmit native handles, naturally <a class="el" href="classipc_1_1transport_1_1Channel.html#aafb0767df5f1dfb535c9467ce717f93f" title="Useful for generic programming: true if and only if types imply at least the blobs pipe is enabled.">ipc::transport::Channel::S_HAS_BLOB_PIPE</a> must be <code>true</code>. (Tweak the <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> compile-time knobs as needed (<a class="el" href="chan_open.html">Sessions: Opening Channels</a>). Specifically set the <code>S_TRANSMIT_NATIVE_HANDLES</code> template parameter to <code>true</code>.)</li>
<li>If <em>and only if</em> for some reason you prefer <em>not</em> to use SHM backing for your <code>struc::Channel</code>, then the max-blob-size enforced by the <code>Channel</code> must be large enough to hold the serialization of any message you choose to send.<ul>
<li>Our advice here: Don't worry about it for now. Just use SHM-backing (we'll explain how shortly). Then size limits won't matter, and you'll get blinding-fast performance automatically.</li>
</ul>
</li>
</ul>
<p >So let's say you have your <code>Channel</code> named <code>unstructured_channel</code>, most easily obtained via <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a>. (If you're the type of person to mind the details &ndash; such a channel from <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> will always be <code>sync_io</code>-core-bearing, meaning it won't have started background threads and is generally lighter-weight.) Do not mutate it in any way. Instead feed it to a constructor of your new <code>struc::Channel</code>.</p>
<p >That's easy enough in and of itself, but you'll need to make a couple of decisions first as to the type of this <code>struc::Channel</code>: it is, also, a <em>template</em>. In this page we're going with the highest-performance, most-mainstream scenario, so we can skip explaining various complexities (leave it to <a class="el" href="chan_struct_advanced.html">Structured Message Transport: Messages As Long-lived Data Structures / Advanced Topics</a>). All <a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">ipc::session::Session</a> concept impls supply a <code>using struc::Channel</code> alias. Thus, as shown in <a class="el" href="session_setup.html">Sessions: Setting Up an IPC Context</a>, you'll have a <code>Session</code> type alias ready. Then:</p>
<div class="fragment"><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> Message_body&gt;</div>
<div class="line"><span class="keyword">using </span>Structured_channel_t = Session::Structured_channel&lt;Message_body&gt;;</div>
</div><!-- fragment --><p >A <em>very</em> central decision is the choice of <code>Message_body</code>. This is the <b>schema</b> of the messages (native handles aside) you intend to transmit back and forth. (Each side must use the same <code>Message_body</code>, or ones that are bit-compatible per capnp requirements.) The design of the schema and the generation of the required header and source-code files are well outside our scope: please see <a href="https://capnproto.org/language.html">capnp schema docs</a> and <a href="https://capnproto.org/capnp-tool.html">capnp tool docs</a>. We shall assume a straightforward schema like this for our example:</p>
<div class="fragment"><div class="line">@0xa780a4869d13f307;</div>
<div class="line">using Cxx = import &quot;/capnp/c++.capnp&quot;;</div>
<div class="line">using Common = import &quot;/ipc/transport/struc/schema/common.capnp&quot;; # Flow-IPC supplies this.</div>
<div class="line"> </div>
<div class="line">$Cxx.namespace(&quot;my_meta_app::capnp&quot;); # capnp-generated structs matching the below will go into this C++ namespace.</div>
<div class="line"> </div>
<div class="line">struct CoolMsg</div>
<div class="line">{</div>
<div class="line">  # This is our root schema; its capnp-generated C++ class will be provided as the Message_body arg to Structured_channel_t.</div>
<div class="line">  # You can have other stuff in this .capnp file; e.g., other schemas for other channels, or totally unrelated</div>
<div class="line">  # items for other purposes if you wish.</div>
<div class="line"> </div>
<div class="line">  union</div>
<div class="line">  {</div>
<div class="line">    # The *only* requirement imposed on your root schema is the root struct *must* contain an anonymous union.</div>
<div class="line">    # (You can also provide non-union fields that apply to all messages.  `description` below is an example of this.)</div>
<div class="line"> </div>
<div class="line">    helloThere @0 :HelloThere;</div>
<div class="line">    # We recommend a convention wherein each top-union member is of a struct type, and the field and type names are</div>
<div class="line">    # equal modulo first-letter capitalization.  However this is completely optional and never relied-upon in any way</div>
<div class="line">    # by Flow-IPC.  Anyway: This HelloThere is one choice for message to send.</div>
<div class="line"> </div>
<div class="line">    sumRequest @1 :SumRequest;</div>
<div class="line">    # This is another choice.  We will use it as an example of a one-off request.</div>
<div class="line"> </div>
<div class="line">    sumResponse @2 :SumResponse;</div>
<div class="line">    # This is another choice.  We will use it as an example of a response to a SumRequest.</div>
<div class="line"> </div>
<div class="line">    hitMeWithYourBestShot @3 :HitMeWithYourBestShot;</div>
<div class="line">    # This one we&#39;ll use to demonstrate indefinite-lifetime request...</div>
<div class="line"> </div>
<div class="line">    myBestShot @4 :MyBestShot;</div>
<div class="line">    # ...together with thise one.</div>
<div class="line">  }</div>
<div class="line"> </div>
<div class="line">  description @5 :Text;</div>
<div class="line">  # As noted you may optionally have items that can be set for every message regardless of the union selector chosen.</div>
<div class="line">  # In this example we&#39;ve provided one such item, a single string named `description`.</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line">struct HelloThere</div>
<div class="line">{</div>
<div class="line">  meaningOfLife @0 :UInt32;</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"># We&#39;ll skip the others for now.</div>
</div><!-- fragment --><p >Once you've run this through <code>capnp</code>, you'll have a <code>class my_meta_app::capnp::CoolMsg</code> available &ndash; notably with nested classes <code>CoolMsg::Reader</code> and <code>CoolMsg::Builder</code>, for reading and mutating such messages respectively. (Please refer to <a href="https://capnproto.org/cxx.html">capnp C++ docs</a> for details.)</p>
<p >Therefore your specific <code>struc::Channel</code> type is easiest to express as follows:</p>
<div class="fragment"><div class="line"><span class="keyword">using </span>Cool_structured_channel = Structured_channel_t&lt;my_meta_app::capnp::CoolMsg&gt;;</div>
</div><!-- fragment --><p >You've got the type; and you've got the (so-far-unused) unstructured <code>Channel unstructured_channel</code>; and you've got the <a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">ipc::session::Session</a> used to open that <code>unstructured_channel</code>. Now it's time to upgrade it into a <code>Cool_structured_channel</code>. Continuing our mainstream-oriented example here's how:</p>
<div class="fragment"><div class="line">Cool_structured_channel cool_channel(..., <span class="comment">// Logger.</span></div>
<div class="line">                                     std::move(unstructured_channel), <span class="comment">// Eat it!</span></div>
<div class="line">                                     <a class="code hl_variable" href="classipc_1_1transport_1_1struc_1_1Channel__base.html#a9bdb94c1ba4fac92fbbd0f843e8525ba">ipc::transport::struc::Channel_base::S_SERIALIZE_VIA_SESSION_SHM</a>,</div>
<div class="line">                                     &amp;session);</div>
<div class="line"><span class="comment">// unstructured_channel is now empty.  cool_channel is however the new hotness.</span></div>
<div class="ttc" id="aclassipc_1_1transport_1_1struc_1_1Channel__base_html_a9bdb94c1ba4fac92fbbd0f843e8525ba"><div class="ttname"><a href="classipc_1_1transport_1_1struc_1_1Channel__base.html#a9bdb94c1ba4fac92fbbd0f843e8525ba">ipc::transport::struc::Channel_base::S_SERIALIZE_VIA_SESSION_SHM</a></div><div class="ttdeci">static constexpr Serialize_via_session_shm S_SERIALIZE_VIA_SESSION_SHM</div><div class="ttdoc">The sole value of the tag type Serialize_via_session_shm.</div><div class="ttdef"><b>Definition:</b> <a href="channel__base_8hpp_source.html#l00160">channel_base.hpp:160</a></div></div>
</div><!-- fragment --><p >The main thing happening here is that 2nd constructor arg: <code>cool_channel</code> empties <code>unstructured_channel</code> and takes over its previous contents. From now on you will be controlling the underlying channel by operating its subsuming <code>struc::Channel</code>. As for the other arguments:</p><ul>
<li><code>&amp;session</code> is straightforward enough: That's the session used to open the channel. Internally it's used for SHM-backing setup and a certain safety mechanism. Bottom line is you need not worry about it. (<a class="el" href="chan_struct_advanced.html">Structured Message Transport: Messages As Long-lived Data Structures / Advanced Topics</a> gets into all that.)</li>
<li><code>S_SERIALIZE_VIA_SESSION_SHM</code> has to do with the lifetime of the SHM-backing for messages. For now don't worry about it. Just know that, as written, a given message object cannot survive the end of <code>session</code>. (There are ways to exceed it; once again that's covered in <a class="el" href="chan_struct_advanced.html">Structured Message Transport: Messages As Long-lived Data Structures / Advanced Topics</a>.)</li>
</ul>
<p >Before we get to sending/receiving messages there's one more &ndash; optional &ndash; thing you may (or may not) wish to get out of the way. The mutually-complementary auto-ping and idle-timer features of <code>Channel</code> are available at this stage. These are discussed in detail in <a class="el" href="transport_core.html">Transport Core Layer: Transmitting Unstructured Data</a>, but the short version is: You may wish for your channel to self-destruct if the other side does not send a message with at least a certain frequency: <b>idle timer</b>. You may, further, wish for (invisible) messages (called <b>auto-pings</b>) to be sent as a form of keep-alive. (<a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a> leverages both features, so that if the other side appears dead due to not even sending auto-pings, the <a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">ipc::session::Session</a> will report an error, at which point you could close all your related channels. Therefore, if you're using <a class="el" href="namespaceipc_1_1session.html" title="Flow-IPC module providing the broad lifecycle and shared-resource organization – via the session conc...">ipc::session</a>, auto-pinging via your own channels may be of little use. However the idle-timer may still be useful by itself depending on your protocol.) Long story short, here is how to do it:</p>
<div class="fragment"><div class="line">Cool_structured_channel cool_channel(...); <span class="comment">// See above.</span></div>
<div class="line"> </div>
<div class="line"><span class="comment">// If desired.  You may also provide an explicit time period as arg instead of the default 2 seconds.</span></div>
<div class="line">cool_channel.owned_channel_mutable()-&gt;auto_ping();</div>
<div class="line"> </div>
<div class="line"><span class="comment">// If desired.  You may also provide an explicit time period as arg instead of the default 5 seconds.</span></div>
<div class="line">cool_channel.owned_channel_mutable()-&gt;idle_timer_run();</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Use cool_channel directly from now on, generally speaking.  (`const` access via</span></div>
<div class="line"><span class="comment">// cool_channel.owned_channel() is okay however.)</span></div>
</div><!-- fragment --><hr  />
<dl class="section user"><dt>sync_io-pattern struc::Channel</dt><dd>In <a class="el" href="async_loop.html">Asynchronicity and Integrating with Your Event Loop</a> we discussed two mutually exclusive (for a given, like, thing &ndash; in this case <code>struc::Channel</code>) APIs. As all over this manual our mainline discussion and examples are written in terms of the async-I/O API. If you wish to use the <code>sync_io</code> alternative (see the aforementioned page for reasons why) then use <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html" title="sync_io-pattern counterpart to async-I/O-pattern transport::struc::Channel.">ipc::transport::struc::sync_io::Channel</a> instead of <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html" title="Owning and wrapping a pre-connected transport::Channel peer (an endpoint of an established channel ov...">ipc::transport::struc::Channel</a>. It is, like all APIs, fully documented in the Reference section of the manual (just click the links in this paragraph to go to the relevant reference pages). The basic things you need to know are:</dd></dl>
<dl class="section user"><dt></dt><dd>The <code>sync_io</code> type is obtained most easily by using the <code><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9426e8e562dd4c9ea1bc1f69f47bb99f" title="Useful for generic programming, the sync_io-pattern counterpart to *this type.">ipc::transport::struc::Channel::Sync_io_obj</a></code> alias. So you could do: <code>using Cool_structured_channel = Structured_channel_t&lt;my_meta_app::capnp::CoolMsg&gt;::Sync_io_obj</code>.</dd></dl>
<dl class="section user"><dt></dt><dd>To create the <code>Cool_structured_channel</code> use the exact same constructor form you would have used with an async-I/O <code>struc::Channel</code>. Therefore the code above constructing the <code>cool_channel</code> would be identical. (Note that both <code>struc::Channel</code>s' constructors take the same <code>sync_io</code>-core-bearing <code>Channel</code> type object to subsume. It does not matter that in one case the result is an async-I/O thing versus a <code>sync_io</code> thing.)</dd></dl>
<dl class="section user"><dt></dt><dd>After that it's a matter of using the documented <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html"><code>sync_io</code> API</a>. It is similar, but not identical, to <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html">the async-I/O one</a>.</dd></dl>
<hr  />
<h2>Using a <code>struc::Channel</code> to transmit </h2>
<p >Naturally you'll need something to send, and therefore receive, before you can do that. You'll need to create an <b>out-message</b> as per <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__out.html" title="A structured out-message suitable to be sent via struc::Channel::send() (et al).">ipc::transport::struc::Msg_out</a> API. Let's get into that.</p>
<h3>Creating and mutating out-messages</h3>
<p ><code>struc::Msg_out</code> is, in essence, not too much different from a container. You declare it; you construct it (on the stack if desired); you mutate it; you destroy it. <code>struc::Msg_out</code>s are not copyable, but they are (cheaply) movable (move-constructible, move-assignable). While they can be constructed explicitly, it's by far easiest to leverage your <code>struc::Channel</code> &ndash; in our case <code>Cool_structured_channel</code>:</p>
<div class="fragment"><div class="line">Cool_structured_channel::Msg_out msg = cool_channel.create_msg();</div>
<div class="line"><span class="comment">// `auto` is fine.  Msg_out shown to make clear this alias is available for other contexts.</span></div>
</div><!-- fragment --><p >Assuming you are familiar with the capnp-generated API, it is straightforward to mutate the (currently blank) <code>msg</code> out-message. The only constraint in terms of the structured content of <code>msg</code> is that (as noted before) at the root level there is a mandatory anonymous <code>union</code>. So let's say we want to send a <code>HelloThere</code> message. Then we could write:</p>
<div class="fragment"><div class="line">msg.body_root() <span class="comment">// This has type CoolMsg::Builder*.</span></div>
<div class="line">  -&gt;initHelloThere() <span class="comment">// Specify top-union-selector (a/k/a union-which) and initialize that struct.</span></div>
<div class="line">    .setMeaningOfLife(42); <span class="comment">// Set a field within that struct.</span></div>
<div class="line">msg.body_root()</div>
<div class="line">  -&gt;setDescription(<span class="stringliteral">&quot;Hello, world -- demo!&quot;</span>); <span class="comment">// Example of setting union-adjacent value (common to all messages).</span></div>
</div><!-- fragment --><hr  />
<dl class="section user"><dt>Quick capnp tips</dt><dd>You should really read all of capnp docs at its web site. They are very useful and well written and not overly formal despite being quite comprehensive. That said a couple of gotchas/tips (taken from <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__out.html#a9894ad7ec2a46641c4b9b86664d0d465">body_root() doc header</a>):</dd></dl>
<dl class="section user"><dt></dt><dd><em>Tip</em>: On a <code>Builder</code>, <code>.getX()</code> and <code>.setX()</code> are lightning-fast, like accessing <code>struct</code> members directly &ndash; but only when <code>X</code> is of a scalar type. Compound types, where <code>.getX()</code> returns not a native type but another <code>Builder</code>, need to perform some pointer checking and are slower. Therefore, if you plan to <code>.getX()</code> and then <code>.setA()</code> and <code>.setB()</code> (and similar) on that <code>X</code>, you should save the result (<code>auto x = ....getX();</code>); then mutate via the saved result (<code>x.setA(...); x.setB(...)</code>).</dd></dl>
<dl class="section user"><dt></dt><dd><em>Tip</em>: Let <code>X</code> be a compound field, particularly <code>List</code>, <code>Text</code> (string/list-of-characters), <code>Data</code> (list-of-bytes). It is usually, to begin, null; you must perform <code>.initX(size_t n)</code> or equivalent to initialize it (fill it with <code>n</code> zeroes). However, suppose you are mutating a message, such as a previously-sent message, and wish to <em>modify</em> the <code>X</code>. If the new value might have the same length (which is common), the correct thing to do is: check <code>.hasX()</code>; if <code>true</code>, modify <code>.getX()</code>; but if <code>false</code> then <code>.initX(n)</code> (as <code>X</code> was null after all). Performing <code>.initX()</code> on an already-<code>.initX()</code>ed value works but has a nasty invisible effect: the existing datum continues taking space in the serialization; the new datum takes a new chunk of the serialization segments (and might even cause the allocation of a new segment if needed). As of this writing capnp does not reuse such orphaned space. If the new <code>n</code> equals the old <code>n</code>, this is a straight waste of RAM; and can lead to pathologically growing memory leaks if done many times.</dd></dl>
<dl class="section user"><dt></dt><dd>(However, if the new <code>n</code> is different from the preceding, then there is no choice but to re-<code>.initX()</code>. A list/blob/string's size cannot be modified in capnp. It is best to avoid any situation where the <code>n</code> would change; try to design your protocol differently.)</dd></dl>
<dl class="section user"><dt></dt><dd><em>Tip</em>: Use <code>ostream &lt;&lt;</code> to pretty-print a <code>struc::Msg_out</code>, without newlines/indentation and truncated as needed to a reasonable length. For fully indented pretty-printing you may use <code>capnp::prettyPrint(msg.body_root()-&gt;asReader()).flatten().cStr()</code>. (Be wary of the perf cost of such an operation, especially for large messages. Though if done within a <code>FLOW_LOG_*()</code> no evaluation occurs, unless the the log-level check passes.)</dd></dl>
<hr  />
<p >More advanced capnp-leveraging operations are possible. We omit detailed discussion here. Briefly:</p><ul>
<li>You can obtain an <code>Orphanage</code> via <code>msg.orphanage()</code> (see <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__out.html#a9303c71f8f459ede25ebe0c8f5492393" title="Convenience method that returns a capnp::Orphan factory in the same capnp::MessageBuilder as body_roo...">ipc::transport::struc::Msg_out::orphanage()</a>). With this you can make objects of any type(s) whatsoever and then <code>adopt...()</code> them in a bottom-up fashion into the ultimate <code>msg.body_root()</code> (which is, rigidly, a <code>CoolMsg::Builder</code>). See capnp docs.</li>
<li>You can go even more capnp-crazy and create a separate <code>capnp::MessageBuilder</code> &ndash; without any particular set root schema &ndash; and then later load it into a <code>struc::Msg_out</code> by using an alternate constructor form. In other words one can use a <code>capnp::MessageBuilder</code> as a heap for arbitrary work. Just ensure that what you're <em>ultimately</em> loading into the <code>struc::Msg_out</code> has most recently been <code>.initRoot&lt;M&gt;()</code>ed, where <code>M</code> matches the <code>Message_body</code> type of your <code>struc::Channel</code>. (So in our example <code>M</code> is <code>CoolMsg</code>.)</li>
</ul>
<p >Lastly, assuming your underlying <code>Cool_structured_channel::Owned_channel</code> is capable of it, any out-message may be paired with a native handle like this:</p>
<div class="fragment"><div class="line"><span class="keyword">using </span><a class="code hl_struct" href="structipc_1_1util_1_1Native__handle.html">ipc::util::Native_handle</a>;</div>
<div class="line"> </div>
<div class="line"><a class="code hl_typedef" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8">Native_handle</a> hndl(some_fd);</div>
<div class="line"><span class="comment">// ...</span></div>
<div class="line">msg.store_native_handle_or_null(std::move(hndl));</div>
<div class="line"><span class="comment">// some_fd is now owned by `msg`.  It will be ::close()d sooner or later.</span></div>
<div class="line"> </div>
<div class="line"><span class="comment">// Beware that `msg`, when destroyed -- or due to a subsequent .store_native_handle_or_null() -- *will* close `some_fd`.</span></div>
<div class="line"><span class="comment">// If you don&#39;t want that, in a POSIX OS you can first dupe it.  For example here we&#39;re sending our own</span></div>
<div class="line"><span class="comment">// standard-output FD in an out-message:</span></div>
<div class="line">msg.store_native_handle_or_null(<a class="code hl_typedef" href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8">Native_handle</a>(::dup(STDOUT_FILENO)));</div>
<div class="line"><span class="comment">// Receiving process -- upon receipt -- can write to that FD and cause output to appear in *our* stdout.</span></div>
<div class="ttc" id="anamespaceipc_1_1transport_html_a7ee4551983d9df16ec16a3139bac50e8"><div class="ttname"><a href="namespaceipc_1_1transport.html#a7ee4551983d9df16ec16a3139bac50e8">ipc::transport::Native_handle</a></div><div class="ttdeci">util::Native_handle Native_handle</div><div class="ttdoc">Convenience alias for the commonly used type util::Native_handle.</div><div class="ttdef"><b>Definition:</b> <a href="transport__fwd_8hpp_source.html#l00081">transport_fwd.hpp:81</a></div></div>
<div class="ttc" id="astructipc_1_1util_1_1Native__handle_html"><div class="ttname"><a href="structipc_1_1util_1_1Native__handle.html">ipc::util::Native_handle</a></div><div class="ttdoc">A monolayer-thin wrapper around a native handle, a/k/a descriptor a/k/a FD.</div><div class="ttdef"><b>Definition:</b> <a href="native__handle_8hpp_source.html#l00062">native_handle.hpp:63</a></div></div>
</div><!-- fragment --><h3>Sending notification messages</h3>
<p >So you've loaded up your <code>struc::Channel::Msg_out</code> a/k/a <code>struc::Msg_out</code>. Now you'll presumably want to send it. The <code>Msg_out</code> is a <b>message</b>, while a message actually sent via channel (and received by the opposing side) is a <b>message instance</b>. Therefore the act of invoking one of the send methods of a <code>struc::Channel</code> (<code>.send()</code>, <code>.async_request()</code>, <code>.sync_request()</code>) creates a message instance from a message &ndash; which the opposing side obtains as an <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html" title="A structured in-message instance suitable as received and emittable (to user) by struc::Channel.">ipc::transport::struc::Msg_in</a> (but more on this later). All properties of a message instance are contained either in the message itself or in the arguments to the chosen <code>struc::Channel</code> send method; they cannot be changed subsequently.</p>
<p >A message is a message; but a message <em>instance</em> is one of 2 things:</p><ul>
<li>A <b>notification</b> message instance is one sent with no expectation of response.<ul>
<li><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448" title="In the synchronous/non-blocking manner of Blob_sender::send_blob() or Native_handle_sender::send_nati...">ipc::transport::struc::Channel::send()</a> classifies the message instance as a notification.</li>
</ul>
</li>
<li>A <b>request</b> message instance is one sent with the expectation that responses to it may arrive in the opposite direction.<ul>
<li><a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346" title="Identical to send() sends the out-message not as a notification but as a request, registering the exp...">ipc::transport::struc::Channel::async_request()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78" title="Equivalent to the other sync_request() overload but with no timeout; meaning it shall exit only once ...">ipc::transport::struc::Channel::sync_request()</a> classifies the message instance as a request.</li>
</ul>
</li>
</ul>
<p >Either type of message &ndash; whether notification or response &ndash; can itself be in response to an earlier-received in-message, or not in response to anything.</p><ul>
<li>One specifies this via an arg to <code>.send()</code> or <code>.*sync_request()</code>.</li>
<li>The act of responding to a notification in-message (instance) is not, in and of itself, an error. Flow-IPC does not check this: you <em>can</em> respond to any message. However, <em>receiving</em> such a message is a (non-fatal) error on the receiver side. More on this shortly. (However, coding reasonably carefully, one can avoid having to worry about it: Only respond to requests when designing your protocol; and cleanly separate requests from notifications when designing your schema, even though Flow-IPC does not force you to do so.)</li>
</ul>
<p >Thus <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ae645cb58ad9ea6374970f1f32c5da448">.send()</a> is the simplest method to demonstrate:</p>
<div class="fragment"><div class="line"><span class="keyword">auto</span> msg = cool_channel.create_msg();</div>
<div class="line">msg.body_root()-&gt;initHelloThere().setMeaningOfLife(42);</div>
<div class="line">msg.body_root()-&gt;setDescription(<span class="stringliteral">&quot;Hello, world -- demo!&quot;</span>);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// .send(): send notification.  No originating_msg_or_null: respond to nothing.</span></div>
<div class="line"><span class="keyword">const</span> <span class="keywordtype">bool</span> ok = cool_channel.send(msg); <span class="comment">// Optional arg: const Msg_in* originating_msg_or_null = nullptr.</span></div>
<div class="line"><span class="comment">// (We discuss error handling in a subsequent section of this page.  For now assume success.)</span></div>
</div><!-- fragment --><p >That's it. A key point: <code>.send()</code> &ndash; as well as <code>.async_request()</code> &ndash;</p><ul>
<li><em>Never</em> blocks.</li>
<li><em>Always</em> finishes synchronously.</li>
<li><em>Never</em> refuses to send due to a <em>would-block</em> condition. (Only a fatal channel-hosing error could occur &ndash; or success.)</li>
</ul>
<p >That last point is unusual but intentionally nice. You <em>never</em> need to worry about a send failing due to a clogged-up low-level transport. (How this is accomplished is discussed in <a class="el" href="transport_core.html">Transport Core Layer: Transmitting Unstructured Data</a> &ndash; but it's an advanced topic, and you can usually just take it for granted.)</p>
<h3>Sending request messages / handling responses</h3>
<p >To send a request use <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a97506bcb695f22e7ca6b480bae5b2346">.async_request()</a> or <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#aa41aee3c76035f43833078e625e6ef78">.sync_request()</a>. The latter blocks until the response arrives and returns the response on success, synchronously.</p>
<dl class="section note"><dt>Note</dt><dd><code>.sync_request()</code> is, indeed, a rare blocking method in Flow-IPC. However in many (certainly not all) situations one can be reasonably assured that a properly behaving opposing process is currently expecting a message of a certain type and will choose to immediately <code>.send()</code> (et al) a response. IPC is meant to be, and is, low-latency &ndash; therefore in such a setup one can reasonably expect a response to arrive with an RTT (round-trip time) of microseconds. Therefore, to simplify code, a <code>.sync_request()</code> <em>can and should</em> be used where possible as a "non-blocking blocking" call. (For worried souls, an optional timeout argument is available.) Otherwise use <code>.async_request()</code> (explained a bit further below).</dd></dl>
<p>Example:</p>
<div class="fragment"><div class="line"># ...(.capnp file continued)...</div>
<div class="line"> </div>
<div class="line">struct SumRequest</div>
<div class="line">{</div>
<div class="line">  # Asks that receiver add up termsToAdd, multiply sum by constantFactor, and return result in</div>
<div class="line">  # SumResponse.</div>
<div class="line"> </div>
<div class="line">  termsToAdd @0 :List(Int64);</div>
<div class="line">  constantFactor @1 :Int64;</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line">struct SumResponse</div>
<div class="line">{</div>
<div class="line">  result @0 :Int64;</div>
<div class="line">}</div>
</div><!-- fragment --><div class="fragment"><div class="line"><span class="keyword">auto</span> msg = cool_channel.create_msg();</div>
<div class="line"><span class="keyword">auto</span> root = msg.body_root()-&gt;initSumRequest();</div>
<div class="line"><span class="keyword">auto</span> list = root.initTermsToAdd(3);</div>
<div class="line">list.set(0, 11);</div>
<div class="line">list.set(1, -22);</div>
<div class="line">list.set(2, 33);</div>
<div class="line">root.setConstantFactor(-2);</div>
<div class="line">msg.body_root()-&gt;setDescription(<span class="stringliteral">&quot;(11 - 22 + 33) x -2 = -44&quot;</span>);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// .sync_request(): send request; synchronously await reply.  No originating_msg_or_null: respond to nothing.</span></div>
<div class="line"><span class="keyword">auto</span> rsp = cool_channel.sync_request(msg,</div>
<div class="line">                                     <span class="keyword">nullptr</span>, <span class="comment">// &lt;-- originating_msg_or_null.</span></div>
<div class="line">                                     boost::chrono::milliseconds(250)); <span class="comment">// Optional timeout arg.</span></div>
<div class="line">assert(rsp &amp;&amp; <span class="stringliteral">&quot;We discuss error handling in a subsequent section of this page.  For now assume success.&quot;</span>);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// The other side had best know how to add stuff and multiply at the end!  Check the in-message.</span></div>
<div class="line">assert(rsp-&gt;body_root().getSumResponse().getResult() == int64_t(-44));</div>
</div><!-- fragment --><hr  />
<dl class="section user"><dt>Sync-request facts</dt><dd>As a rare blocking method there are a few things to note about it.</dd></dl>
<dl class="section user"><dt></dt><dd><code>.sync_request()</code> blocks up to the timeout; but if a channel-hosing error occurs during its operation it will return immediately emitting the error (which may or may not be specifically related to the send attempt itself). (We discuss error handling in more detail below.) However the specific <em>timeout</em> error is <em>not fatal</em>: <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297abcfca4c2347f9d377dd2ac41c41dc027" title="A (usually user-specified) timeout period has elapsed before a blocking operation completed.">ipc::transport::error::Code::S_TIMEOUT</a>.</dd></dl>
<dl class="section user"><dt></dt><dd>If a timeout does occur, a late-arriving response (if one indeed occurs) shall be ignored by Flow-IPC (as-if it was never received, modulo some logging).</dd></dl>
<dl class="section user"><dt></dt><dd><code>.sync_request()</code> is not special in terms of thread safety: You may not invoke other methods concurrently on the same <code>struc::Channel</code>, until it has returned.</dd></dl>
<dl class="section user"><dt></dt><dd>A request made via <code>.sync_request()</code> is by definition <b>one-off</b>: If the opposing side sends 2 or more responses, all but the first will be ignored (logging aside), except unexpected-response handler(s) may fire (more on this below). C/f <code>.async_request()</code> which allows one-off and <b>indefinite-lifetime</b> requests alike.</dd></dl>
<hr  />
<p >That brings us to <code>.async_request()</code>, the other way of sending a message (turning it into a message instance) while expecting response(s). Depending on the situation it may be less or more mainstream than <code>.sync_request()</code>. An async-request is as follows:</p><ul>
<li>One sends a message, simultaneously registering a <b>response handler</b> which, if invoked, shall be given the resulting in-message as an argument.</li>
<li>At the same time, using an argument to <code>.async_request()</code>, one specifies whether:<ul>
<li>the response expectation is <b>one-off</b> (once response does arrive, the expectation is automatically removed, and the handler is forgotten); or</li>
<li>the response expectation is <b>indefinite-lifetime</b> (multiple response may arrive, each time firing the handler; the response expectation may be removed manually using <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a34780bd3507a571cb719ce1d59e5d56f" title="Unregisters the expectation earlier-registered with the id_unless_one_off != nullptr form of async_re...">ipc::transport::struc::Channel::undo_expect_responses()</a>).</li>
</ul>
</li>
</ul>
<p >In any case, if the opposing side sends a response that is not expected at a given time, it is ignored (logging aside), except unexpected-response handler(s) may fire (more on this below).</p>
<p >We've already demonstrated (more or less) dealing with a one-off request, so for this example let's issue an indefinite-lifetime one.</p>
<div class="fragment"><div class="line"># ...(.capnp file continued)...</div>
<div class="line"> </div>
<div class="line">struct HitMeWithYourBestShot</div>
<div class="line">{</div>
<div class="line">  # A single request will be issued, and multiple responses may arrive as a result.</div>
<div class="line"> </div>
<div class="line">  # ...we&#39;ll skip the specifics -- use your imagination.</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line">struct MyBestShot</div>
<div class="line">{</div>
<div class="line">  # A response.</div>
<div class="line"> </div>
<div class="line">  moreComing @0 :Bool;</div>
<div class="line">  # In this example the response will itself specify whether more responses might arrive.</div>
<div class="line"> </div>
<div class="line">  # ...we&#39;ll skip further specifics -- use your imagination.</div>
<div class="line">}</div>
</div><!-- fragment --><p >This following code assumes an async-I/O event loop setup introduced <a href="./async_loop.html#aio_pattern">here</a> &ndash; in this case a single thread called thread W, onto which further tasks may be posted using a <code>post()</code> function.</p>
<div class="fragment"><div class="line"><span class="comment">// Sender side: Your async-I/O loop&#39;s main thread W.</span></div>
<div class="line"> </div>
<div class="line"><span class="keyword">auto</span> msg = cool_channel.create_msg();</div>
<div class="line"><span class="keyword">auto</span> root = msg.body_root()-&gt;initHitMeWithYourBestShot();</div>
<div class="line"><span class="comment">// ...Fill out `root`....</span></div>
<div class="line">msg.body_root()-&gt;setDescription(<span class="stringliteral">&quot;single request, indefinite-lifetime&quot;</span>);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// .async_request(): send request; asynchronously await reply.  No originating_msg_or_null: respond to nothing.</span></div>
<div class="line"> </div>
<div class="line">Cool_structured_channel::msg_id_out_t req_handle; <span class="comment">// Used to be able to remove response expectation later.</span></div>
<div class="line"> </div>
<div class="line"><span class="keyword">const</span> <span class="keywordtype">bool</span> ok = cool_channel.async_request(msg,</div>
<div class="line">                                           <span class="keyword">nullptr</span>, <span class="comment">// &lt;-- originating_msg_or_null.</span></div>
<div class="line">                                           &amp;req_handle, <span class="comment">// (Would have used nullptr for one-off request.)</span></div>
<div class="line">                                           [<span class="keyword">this</span>, req_handle](Cool_structured_channel::Msg_in_ptr&amp;&amp; rsp)</div>
<div class="line">                                             <span class="comment">// Note: In some cases you may need `mutable` keyword here.</span></div>
<div class="line">{</div>
<div class="line">  <span class="comment">// We are unspecified thread (async-I/O pattern).  Offload true handling back onto your thread W.</span></div>
<div class="line">  <span class="comment">//</span></div>
<div class="line">  <span class="comment">// Caution!  This is *not* a one-off request, hence the present code may run 2+ times.  If you captured</span></div>
<div class="line">  <span class="comment">// something more than `this` and `req_handle` here, you need to be careful when using std::move() in your</span></div>
<div class="line">  <span class="comment">// capture.  In a one-off request it is fine; but otherwise a destructive move()ing capture may cause a nasty</span></div>
<div class="line">  <span class="comment">// surprise on 2nd, 3rd, ... response: Whatever you move()d the 1st time may have been emptied/otherwise messed</span></div>
<div class="line">  <span class="comment">// over for the subsequent times.  You may need to copy whatever it is.  If the copy is too expensive:</span></div>
<div class="line">  <span class="comment">// use a shared_ptr&lt;&gt; wrapper (shared_ptr copies are pretty cheap).</span></div>
<div class="line">  post([<span class="keyword">this</span>, req_handle,</div>
<div class="line">        <span class="comment">// For a perf boost use move() here to avoid ref-counting overhead.  `rsp` is a shared_ptr&lt;Msg_in&gt;.</span></div>
<div class="line">        rsp = std::move(rsp)]()</div>
<div class="line">  {</div>
<div class="line">    <span class="comment">// We are back in: Your async-I/O loop&#39;s main thread W.</span></div>
<div class="line"> </div>
<div class="line">    <span class="keyword">const</span> <span class="keywordtype">bool</span> more_coming = rsp-&gt;body_root().getMyBestShot().getMoreComing();</div>
<div class="line"> </div>
<div class="line">    FLOW_LOG_TRACE(<span class="stringliteral">&quot;Got message [&quot;</span> &lt;&lt; *rsp &lt;&lt; <span class="stringliteral">&quot;] including description [&quot;</span> &lt;&lt; rsp-&gt;body_root().getDescription() &lt;&lt; <span class="stringliteral">&quot;]; &quot;</span></div>
<div class="line">                   <span class="stringliteral">&quot;it specifies more responses may arrive? = [&quot;</span> &lt;&lt; more_coming &lt;&lt; <span class="stringliteral">&quot;].&quot;</span>);</div>
<div class="line">    <span class="comment">// ...Handle further rsp-&gt;body_root() payload....</span></div>
<div class="line"> </div>
<div class="line">    <span class="keywordflow">if</span> (!more_coming)</div>
<div class="line">    {</div>
<div class="line">      <span class="keyword">const</span> <span class="keywordtype">bool</span> ok = cool_channel.undo_expect_responses(req_handle);</div>
<div class="line">      assert(ok &amp;&amp; <span class="stringliteral">&quot;We discuss error handling in a subsequent section of this page.  For now assume success.&quot;</span>);</div>
<div class="line">    }</div>
<div class="line">  }); <span class="comment">// post()</span></div>
<div class="line">}); <span class="comment">// cool_channel.async_request()</span></div>
<div class="line">assert(ok &amp;&amp; <span class="stringliteral">&quot;We discuss error handling in a subsequent section of this page.  For now assume success.&quot;</span>);</div>
</div><!-- fragment --><hr  />
<dl class="section user"><dt>sync_io-pattern and async-request</dt><dd>Using <code>sync_io</code>-pattern <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a26dc83067e005be38567199cbedd7f19" title="See Async_io_obj counterpart; though naturally on_rsp_func() is invoked in the sync_io-pattern fashio...">ipc::transport::struc::sync_io::Channel::async_request()</a> conceptually is quite similar to the async-I/O one shown above, and the code will likely look fairly similar too. As usual with <code>sync_io</code> pattern, however, the handler no longer fires from some unknown (to you) thread, but instead only potentially <em>synchronously</em> from within your successful async-wait's call into <code>(*on_active_ev_func)()</code>.</dd></dl>
<dl class="section user"><dt></dt><dd>Accordingly there wouldn't be the intermediate <code>post()</code> step inside the handler given to <code>.async_request()</code> in the above code.</dd></dl>
<dl class="section user"><dt></dt><dd>Since it is impossible for a response to already be synchronously available at the time of the <code>.async_request()</code>, there is no need to worry about that possibility: The response always arrives later on an active event that your own code would have detected (e.g., via <code>epoll_wait()</code> or boost.asio <code>.async_wait()</code>). Contrast this with <code>.expect_msg()</code> (et al), discussed below.</dd></dl>
<dl class="section user"><dt></dt><dd>All in all this sidebar is here essentially because, chronologically speaking, it is the first time we've gone into event handling in <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a> in this Manual. Upon practice/familiarity with async-I/O and/or <code>sync_io</code> patterns, these things will hopefully become second-nature. I.e., none of this is really "special" or particularly applicable to <code>.async_request()</code> or even <code>struc::Channel</code> specifically. We are just trying to be reader-friendly for first-time users.</dd></dl>
<hr  />
<p >That was quite a lot of stuff; and indeed we've covered at least 50% of the <code>struc::Channel</code> experience, so to speak. That said we've intentionally only demonstrated the sender side of this thing, venturing into in-message analysis only tangentially when it concerned dealing with responses to requests. Now let's jump into the opposing side of these examples, as it is a convenient way to explore expecting notifications and requests in the first place. An analogy: if we'd been discussing how an HTTP GET request works, so far we've covered the client side of it &ndash; issuing the GET request among others. Now to discuss the server side &ndash; expecting a GET and replying to it.</p>
<h3>Expecting notifications and requests; responding to requests</h3>
<p >You might recall from earlier in this page that Flow-IPC imposes a single restriction on the schema <code>Message_body</code> of <code>struc::Channel&lt;Message_body&gt;</code> (in our case <code>Message_body</code> is <code>CoolMsg</code>). That restriction is <code>Message_body</code> must have an anonymous capnp-<code>union</code> at the root. The reason is, specifically, how the <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0">.expect_msg()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67">.expect_msgs()</a> APIs work. Each takes two main arguments:</p><ul>
<li>The <b>unsolicited-message handler</b> function to invoke upon receipt of the <b>unsolicited message</b>.</li>
<li>The <code>union</code>-selector (a/k/a <b>union-which</b> value) of the message. Basically it's the root <em>type</em> of the message. E.g., in HTTP the union-which possibilities are GET, POST, etc. In our example they, specifically, are: <code>HELLO_THERE</code>, <code>SUM_REQUEST</code>, <code>SUM_RESPONSE</code>, <code>HIT_ME_WITH_YOUR_BEST_SHOT</code>, <code>MY_BEST_SHOT</code>. (Per capnp convention, these names are generated from the <code>union</code> field names; so <code>helloThere</code> -&gt; <code>HELLO_THERE</code>, and so on.)<ul>
<li>In our example <code>SUM_RESPONSE</code> and <code>MY_BEST_SHOT</code>-type messages are only used as responses. Therefore we won't <code>.expect_msg*()</code> them. (We could though, if we wanted. See following side-bar.)</li>
</ul>
</li>
</ul>
<p >The <code>union</code>-selector type (generated by capnp) is, for your convenience, aliased as <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9a0382aa663c177f2a38b576d06b251e">struc::Channel::Msg_which</a>. capnp-familiar people will recognize it as <code>struc::Channel::Msg_body::Which</code> (in our case <code>CoolMsg::Which</code>). It is a C++ scoped-enumeration (<code>enum class</code>) which is light-weight like an <code>int</code>.</p>
<hr  />
<dl class="section user"><dt>Subtleties regarding unsolicited message versus response</dt><dd>Each in-message instance is, in purely binary fashion, <em>either</em> a <b>response</b> <em>or</em> an <b>unsolicited message</b>. The sender specifies this by supplying either <code>nullptr</code>, or not, for the <code>originating_msg_or_null</code> argument to <code>.send()</code>, <code>.async_request()</code>, or <code>.sync_request()</code>. Thus: <code>originating_msg_or_null == nullptr</code> if and only if it's an unsolicited message instance.</dd></dl>
<dl class="section user"><dt></dt><dd>So suppose an in-message arrives, and it is a response. Then: either there's a response expectation registered for it (and it is emitted to the user, you); or not (and it is dropped modulo logging and unexpected-response handlers discussed below). It <em>does not matter</em> if there is an active <code>.expect_msg()</code> or <code>.expect_msgs()</code> for that union-which value. It's a response; that's it; either it's expected, or it's not.</dd></dl>
<dl class="section user"><dt></dt><dd>Conversely if an in-message arrives, and it is <em>not</em> a response, then it goes down the unsolicited-message code path discussed below. Spoiler alert: If an <code>expect_msg*()</code> is active, then it is immediately emitted to you, the user; if not, then it is cached inside the <code>struc::Channel</code> and may be emitted later once (and if) an <code>expect_msg*()</code> happens to get called by you.</dd></dl>
<dl class="section user"><dt></dt><dd>In the spirit of flexibility and tolerance Flow-IPC allows one to <code>expect_*()</code> messages that may also be issued as responses. That is, in the schema, there is no formal way to classify a union-which (message type) as either a response or an unsolicited message; any message can be either. Informally, though, we recommend that you clearly <em>do</em> classify each message as exactly one or the other. (A convention like an <code>Rsp</code> postfix for responses might be a decent idea.) In HTTP, you'd <em>expect</em> an <em>unsolicited</em> GET; but you'd never <em>expect</em> an unsolicited GET-response. We recommend following the same principle in your meta-application and schema. Otherwise it's an avoidable mess.</dd></dl>
<hr  />
<dl class="section note"><dt>Note</dt><dd>To put a fine point on it: A message instance is either unsolicited or a response; and <em>orthogonally</em> it is either a request or a notification. Hence, e.g., a message instance can be both a response and a request (like a single ping-pong exchange). The latter is expressed by the choice of send-API called (<code>.send()</code> or <code>.*_request()</code>); the former by the value of <code>originating_msg_or_null</code> arg to the send-API.</dd></dl>
<p>That said/understood, the <code>.expect_msg*()</code> APIs are fairly similar to <code>.async_request()</code> &ndash; the differences being:</p><ul>
<li>There's no message instance sent as a way to solicit the in-message(s) (hence the term <em>unsolicited</em> in-message).</li>
<li>There are two separate methods for <b>one-off</b> versus <b>indefinite-lifetime</b> modes instead of an argument: <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a160a8d49624f15a2596ee7b0244584b0">.expect_msg()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a3376b821b129ca3847484a178e080c67">.expect_msgs()</a> respectively.<ul>
<li>To remove the expectation registered by <code>.expect_msgs()</code> one uses <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a896bb326a58f433bade75b62f1893462">.undo_expect_msgs()</a> which is analogous to <code>.undo_expect_responses()</code>. No particular generated ID is necessary: one simply supplies the same union-which value as earlier given to <code>.expect_msgs()</code>.</li>
</ul>
</li>
</ul>
<p >We can now demonstrate both <code>.expect_msg*()</code> methods by completing the other side of our one-off <code>SumRequest</code> and indefinite-lifetime <code>HitMeWithYourBestShot</code> examples. As a little bonus this lets us show the use of the <code>originating_msg_or_null</code> arg to <code>.send()</code> (et al). Again &ndash; by doing this we classify that message instance as a response rather than unsolicited.</p>
<p >One-off example first:</p>
<div class="fragment"><div class="line"><span class="comment">// Receiver side: Your async-I/O loop&#39;s main thread W.</span></div>
<div class="line"> </div>
<div class="line"><span class="keyword">const</span> <span class="keywordtype">bool</span> ok = cool_channel.expect_msg(Cool_structured_channel::Msg_which::SUM_REQUEST, <span class="comment">// &lt;=&gt; sumRequest union field.</span></div>
<div class="line">                                        [<span class="keyword">this</span>](Cool_structured_channel::Msg_in_ptr&amp;&amp; req)</div>
<div class="line">{</div>
<div class="line">  <span class="comment">// We are unspecified thread (async-I/O pattern).  Offload true handling back onto your thread W.</span></div>
<div class="line">  post([<span class="keyword">this</span>,</div>
<div class="line">        <span class="comment">// For a perf boost use move() here to avoid ref-counting overhead.  `req` is a shared_ptr&lt;Msg_in&gt;.</span></div>
<div class="line">        req = std::move(req)]()</div>
<div class="line">  {</div>
<div class="line">    <span class="comment">// We are back in: Your async-I/O loop&#39;s main thread W.</span></div>
<div class="line"> </div>
<div class="line">    int64_t sum = 0;</div>
<div class="line">    <span class="keyword">const</span> <span class="keyword">auto</span> sum_func = [&amp;](int64_t val) { sum += val; };</div>
<div class="line">    <span class="keyword">auto</span> root = req-&gt;body_root().getSumRequest();</div>
<div class="line">    <span class="keyword">auto</span> list = root.getTermsToAdd();</div>
<div class="line">    std::for_each(list.begin(), list.end(), sum_func);</div>
<div class="line">    sum *= root.getConstantFactor();</div>
<div class="line"> </div>
<div class="line">    FLOW_LOG_TRACE(<span class="stringliteral">&quot;Got request [&quot;</span> &lt;&lt; *req &lt;&lt; <span class="stringliteral">&quot;] including description &quot;</span></div>
<div class="line">                   <span class="stringliteral">&quot;[&quot;</span> &lt;&lt; req-&gt;body_root().getDescription() &lt;&lt; <span class="stringliteral">&quot;]; responding with result [&quot;</span> &lt;&lt; sum &lt;&lt; <span class="stringliteral">&quot;].&quot;</span>);</div>
<div class="line"> </div>
<div class="line">    <span class="keyword">auto</span> msg = cool_channel.create_msg();</div>
<div class="line">    msg.body_root()-&gt;initSumResponse().setResult(sum);</div>
<div class="line">    msg.body_root()-&gt;setDescription(<span class="stringliteral">&quot;the sum you ordered, sir&quot;</span>);</div>
<div class="line"> </div>
<div class="line">    <span class="keyword">const</span> <span class="keywordtype">bool</span> ok = msg.send(msg,</div>
<div class="line">                             req.get()); <span class="comment">// &lt;-- originating_msg_or_null.  We are responding.</span></div>
<div class="line">    assert(ok &amp;&amp; <span class="stringliteral">&quot;We discuss error handling in a subsequent section of this page.  For now assume success.&quot;</span>);</div>
<div class="line">  }); <span class="comment">// post()</span></div>
<div class="line">}); <span class="comment">// cool_channel.async_request()</span></div>
<div class="line">assert(ok &amp;&amp; <span class="stringliteral">&quot;We discuss error handling in a subsequent section of this page.  For now assume success.&quot;</span>);</div>
</div><!-- fragment --><p >Indefinite-lifetime variation is essentially similar. In our example the idea is to send responses at various times, not necessarily immediately upon receiving request, so the example code will be somewhat hand-wavy (we are confident you can fill in the blanks).</p>
<div class="fragment"><div class="line"><span class="comment">// Receiver side: Your async-I/O loop&#39;s main thread W.</span></div>
<div class="line"> </div>
<div class="line"><span class="keyword">const</span> <span class="keywordtype">bool</span> ok = cool_channel.expect_msgs(Cool_structured_channel::Msg_which::HIT_ME_WITH_YOUR_BEST_SHOT,</div>
<div class="line">                                         [<span class="keyword">this</span>](Cool_structured_channel::Msg_in_ptr&amp;&amp; req)</div>
<div class="line">                                             <span class="comment">// Note: In some cases you may need `mutable` keyword here.</span></div>
<div class="line">{</div>
<div class="line">  <span class="comment">// We are unspecified thread (async-I/O pattern).  Offload true handling back onto your thread W.</span></div>
<div class="line">  <span class="comment">//</span></div>
<div class="line">  <span class="comment">// Caution!  This is *not* a one-off expectation, hence the present code may run 2+ times.  If you captured</span></div>
<div class="line">  <span class="comment">// something more than `this` here, you need to be careful when using std::move() in your</span></div>
<div class="line">  <span class="comment">// capture.  In a one-off request it is fine; but otherwise a destructive move()ing capture may cause a nasty</span></div>
<div class="line">  <span class="comment">// surprise on 2nd, 3rd, ... response: Whatever you move()d the 1st time may have been emptied/otherwise messed</span></div>
<div class="line">  <span class="comment">// over for the subsequent times.  You may need to copy whatever it is.  If the copy is too expensive:</span></div>
<div class="line">  <span class="comment">// use a shared_ptr&lt;&gt; wrapper (shared_ptr copies are pretty cheap).</span></div>
<div class="line">  post([<span class="keyword">this</span>,</div>
<div class="line">        <span class="comment">// For a perf boost use move() here to avoid ref-counting overhead.  `req` is a shared_ptr&lt;Msg_in&gt;.</span></div>
<div class="line">        req = std::move(req)]()</div>
<div class="line">  {</div>
<div class="line">    <span class="comment">// We are back in: Your async-I/O loop&#39;s main thread W.</span></div>
<div class="line"> </div>
<div class="line">    <span class="comment">// ...Check out `req`; set up whatever logic needed to subsequently/asynchronously send 0+ responses....</span></div>
<div class="line">    <span class="comment">// ...For example when sending the last response we would send to this request, we would do:</span></div>
<div class="line"> </div>
<div class="line">    <span class="keyword">auto</span> msg = cool_channel.create_msg();</div>
<div class="line">    <span class="comment">// ...</span></div>
<div class="line">    msg.body_root()-&gt;setMoreExpected(<span class="keyword">false</span>);</div>
<div class="line">    msg.body_root()-&gt;setDescription(<span class="stringliteral">&quot;last response to request&quot;</span>);</div>
<div class="line"> </div>
<div class="line">    <span class="comment">// (To keep responding to `req`, `req` needs to be kept around and available for each .send().</span></div>
<div class="line">    <span class="comment">// It&#39;s a shared_ptr&lt;&gt;, so it should not be a big deal perf-wise or RAM-wise.)</span></div>
<div class="line">    <span class="keyword">const</span> <span class="keywordtype">bool</span> ok = msg.send(msg,</div>
<div class="line">                             req.get()); <span class="comment">// &lt;-- originating_msg_or_null.  We are responding.</span></div>
<div class="line">    assert(ok &amp;&amp; <span class="stringliteral">&quot;We discuss error handling in a subsequent section of this page.  For now assume success.&quot;</span>);</div>
<div class="line"> </div>
<div class="line">    <span class="comment">// Moreover, perhaps we only take such a request only once at most.  In which case:</span></div>
<div class="line"> </div>
<div class="line">    <span class="comment">// Note we remove expectation by using the same Msg_which union-which value as .expect_msgs().</span></div>
<div class="line">    ok  = cool_channel.undo_expect_response(Cool_structured_channel::Msg_which::HIT_ME_WITH_YOUR_BEST_SHOT);</div>
<div class="line">    assert(ok &amp;&amp; <span class="stringliteral">&quot;We discuss error handling in a subsequent section of this page.  For now assume success.&quot;</span>);</div>
<div class="line"> </div>
<div class="line">    <span class="comment">// ...</span></div>
<div class="line">  }); <span class="comment">// post()</span></div>
<div class="line">}); <span class="comment">// cool_channel.async_request()</span></div>
<div class="line">assert(ok &amp;&amp; <span class="stringliteral">&quot;We discuss error handling in a subsequent section of this page.  For now assume success.&quot;</span>);</div>
</div><!-- fragment --><p >And that's it! We have pretty much used the entire essential arsenal now. That said a few side-bars:</p>
<hr  />
<dl class="section user"><dt>What is an in-message?</dt><dd>An <em>in-message instance</em> is represented by, as we've seen, a <code>struc::Channel::Msg_in_ptr</code> which is but a <code>shared_ptr&lt;Msg_in&gt;</code>; while <code>Msg_in</code> is itself an instance of the <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html" title="A structured in-message instance suitable as received and emittable (to user) by struc::Channel.">ipc::transport::struc::Msg_in</a> class template. Its basic capabilities you've already seen: <code>.body_root()</code> to get at the structured data via capnp-generated <code>Reader</code>; <code>ostream &lt;&lt;</code> to pretty-print a potentially-truncated un-indented version (potentially slow but okay in TRACE-logging and the like); and so on.</dd></dl>
<dl class="section user"><dt></dt><dd>One we have not yet mentioned is: A <code>Native_handle</code> stored in the original <b>message</b> (<code>struc::Msg_out</code> a/k/a <code>struc::Channel::Msg_out</code>) can of course be obtained from the in-message instance. Use <a class="el" href="classipc_1_1transport_1_1struc_1_1Msg__in.html#aba0b83c9d8a7e8f782202406ca387e2c" title="The Native_handle – potentially null meaning none – embedded in this message.">ipc::transport::struc::Msg_in::native_handle_or_null()</a>. One subtlety to note here: unlike <code>Msg_out</code> destructor, <code>Msg_in</code> destructor will <em>not</em> close the <code>Native_handle</code> if any. What to do with this native handle (FD in POSIX parlance) is entirely your call. Do note that in POSIX/Unix/Linux this FD refers to the same resource <em>description</em> as the original sent FD from the origin process; but it is <em>not</em> the same <em>descriptor</em>. The <em>description</em> will itself be released back into the OS's resource pool no earlier than <em>both</em> the original sendable-FD and the received-FD have been closed. So: unless you want that resource to leak, it is your reponsibility to take ownership of it. Hopefully the task is made easier by the sent-message <code>Msg_out</code> (the actual <b>message</b>, not merely the <b>message instance</b> sent) guaranteeing the closure of the sendable-FD no later than <code>Msg_out</code> being destroyed... so the send-side will not be the source of the leak.</dd></dl>
<dl class="section user"><dt></dt><dd>On a related note: A particular <code>Msg_in</code> (<code>struc::Msg_in&lt;...&gt;</code>) object represents a message <em>instance</em>. That is it represents a message <em>as sent and received that particular time</em>. A <code>Msg_out</code> can be re-sent later; and it can even be modified and re-sent (as many times as desired). We'll cover that in <a class="el" href="chan_struct_advanced.html">Structured Message Transport: Messages As Long-lived Data Structures / Advanced Topics</a> &ndash; but be aware of it even now. Spoiler alert: If SHM-backing is configured (as we generally recommend), then the original <code>Msg_out</code> <em>and</em> any <code>Msg_in</code> in existence (and there can be multiple) really refer to the same RAM resource. Hence the RAM is returned for other use no sooner than all those guys have been destroyed (across all processes involved). If SHM-backing is <em>not</em> used, then each <code>Msg_in</code> is really a copy of the original, and therefore the <code>Msg_out</code> and all derived <code>Msg_in</code>s are independent, returning each RAM resource on destruction of that object.</dd></dl>
<dl class="section user"><dt></dt><dd>However that applies only to the structured data. The <code>Native_handle</code>s are always, conceptually speaking, copies of the original one(s) (if any) in <code>Msg_out</code>. Again we'll get into all this in <a class="el" href="chan_struct_advanced.html">Structured Message Transport: Messages As Long-lived Data Structures / Advanced Topics</a> &ndash; so consider these paragraphs a brief intro to that stuff.</dd></dl>
<dl class="section user"><dt>Unexpected-message handling</dt><dd>A few times we've now mentioned the possibility of an in-message (instance) arriving, when an expectation for it was not registered in the receiving <code>struc::Channel</code>.</dd></dl>
<dl class="section user"><dt></dt><dd>To recap: If an <em>unsolicited</em> in-message arrives, and it's not <code>expect_*()</code>ed, it is cached. A subsequent <code>expect_msg*()</code> may therefore be immediately satisfied by a cached such in-message instance. This is in no way an error. In fact it is an important property: It means no unsolicited message is ever dropped or lost due to not been expected "in time." Also important: any cached messages are emitted to the user &ndash; when officially expected and no earlier &ndash; in the same order as they were sent. They will not be reordered among each other! The only way to reorder the handling of in-messages is by expecting message type B before message type A, causing the latter to be cached and not emitted in the meantime. E.g., if one <code>expect_msgs()</code> GETs a second after <code>expect_msgs()</code> POSTs, some GETs may be sent before some POSTs but get cached until the somewhat-delayed <code>expect_msgs(GET)</code>. However, all those GETs <em>will</em> get emitted to you in a burst and strictly in the order they were sent.</dd></dl>
<dl class="section user"><dt></dt><dd>One thing to watch out for here is simply that cached in-messages take up RAM/resources. This is usually fine; but generally speaking you'll want to <code>expect_*()</code> stuff as early as possible to prevent pathological RAM use.</dd></dl>
<dl class="section user"><dt></dt><dd>Now then: That's about unsolicited messages. <em>Responses</em> are different. Receiving a response, when no applicable response expectation has been registered via <code>.async_request()</code> or <code>.sync_request()</code>, is an error condition but <em>not</em> a channel-hosing one. (A response to <code>.sync_request()</code> received after that call timed out is just dropped; that's it. This is not what we are discussing here.) All such situations &ndash; a response to a non-request; a response to a one-off request that has already been satisfied; a response after <code>.undo_expect_responses()</code> &ndash; result in the following steps. The response is dropped. <em>If</em> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab7cd0bed6392cb155f9ee21071c5226b" title="Registers the handler to invoke when a response in-message arrives, but no response-expectation has b...">ipc::transport::struc::Channel::set_unexpected_response_handler()</a> is in effect, then that handler is invoked informing you of the unexpected response. Furthermore, via an internal mechanism, the sender-side of the bad response is informed of this situation as well. On <em>that</em> side: <em>If</em> <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a9ec7ff431b51fec8aacacccb23a2d4e3" title="Registers the handler to invoke when the remote peer encounters the condition that would fire the rem...">ipc::transport::struc::Channel::set_remote_unexpected_response_handler()</a> is in effect, then that handler is invoked informing you of the unexpected response sent <em>by you</em>.</dd></dl>
<dl class="section user"><dt></dt><dd>That feature &ndash; the local and "remote" unexpected-reponse notification &ndash; may be useful. Informally, though, we would suggest designing a protocol in robust enough fashion to where these guys firing would be impossible. It should really, usually, be possible to lock down your protocol to avoid races or corner cases of that nature. Though, who knows? It's conceivable that it's not always so easy. Just saying: try to keep it simple.</dd></dl>
<dl class="section user"><dt>sync_io-pattern and expect-message(s)</dt><dd>The doc header for <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a5fc489b9abefe5ab676f6991d6d03f0d" title="Registers the expectation (which may be immediately met) of up to 1 notification in-message whose Msg...">ipc::transport::struc::sync_io::Channel::expect_msg()</a> and <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a62f52488ba20dd6c69dfc1abadb2d69f">.expect_msgs()</a> explains the deal. For your convenience here, though, spoiler alert: As noted above, async-I/O <code>.expect_msg*()</code> may trigger a "burst" of cached in-message(s) being emitted via the very handler that was just given to that method; but with <code>sync_io</code> pattern this situation creates a dichotomy: An in-message being available immediately is not quite the same as one being available asynchronously later. Therefore the <code>sync_io</code>-pattern <code>.expect_msg*()</code> API features an extra out-argument. If message(s) is/are available synchronously, it/they is/are synchronously output right into that argument. (<code>.expect_msg()</code>, natually, emits up to 1 in-message, and if 1 was indeed emitted does not register an expectation for more &ndash; and forgets the handler, never invoking it. <code>.expect_msgs()</code> can emit multiple in-messages synchronously into a user-supplied sequence container, and even if it does so, it remembers the handler in case more arrive later.)</dd></dl>
<hr  />
<h2>Starting channel; errors; channel destruction </h2>
<p >While above we covered all the fun stuff &ndash; actual transmission APIs &ndash; we glossed over certain less-enjoyable aspects which are nevertheless critical to understand to use <code>struc::Channel</code>. These concern beginning work on a given channel; what errors might occur and how they are emitted; and destroying the <code>struc::Channel</code> properly.</p>
<p >The first thing to grok is that channel operations are divided into 2 categories: <b>incoming-direction</b> ops and <b>outgoing-direction</b> ops. Outgoing-direction ops are simply: <code>.send()</code> and the synchronous work performed by <code>.async_request()</code> and <code>.sync_request()</code>. (<code>.sync_request()</code> is entirely synchronous; <code>.async_request()</code> has a synchronous part as well as the potential response(s) arriving later; only the former part of <code>.async_request()</code> is classified as <em>outgoing-direction</em>.) Incoming-direction ops are everything else and comprise the receipt of unsolicited messages (emission-to-user of which is controlled by <code>expect_*()</code>) and responses (emission-to-user of which is controlled by <code>.async_request()</code>).</p>
<h3>Starting channel</h3>
<p >Obviously first you need to construct the <code>struc::Channel</code>. We've covered that. (If using <code>sync_io</code>-pattern <code>struc::Channel</code>, you'll need to also call <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a6e4f8c4207fcf678b4cfc785707d3dce" title="Sets up the sync_io-pattern interaction between *this and the user&#39;s event loop; required before star...">ipc::transport::struc::sync_io::Channel::start_ops()</a> and possibly <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a543aa806ec21b8550f9f440e59767d52">.replace_event_wait_handles()</a>.)</p>
<p >Having done this you can immediately use <em>outgoing-direction</em> op <code>.send()</code> (and <code>.async_end_sending()</code>). You may not use <code>.sync_request()</code> yet; and while you can call <code>.async_request()</code> to send the request itself, no responses will be received or emitted to your handler yet.</p>
<p >You can also call <em>incoming-direction</em> APIs including <code>.expect_*()</code>, but no relevant in-messages will yet be received or emitted to you. To be able to fully use the <code>struc::Channel</code> you must call:</p><ul>
<li>(async-I/O) <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#a33b4785c212ad88d8322fcc2f4369351">.start()</a>; or</li>
<li>(<code>sync_io</code>) <a class="el" href="classipc_1_1transport_1_1struc_1_1sync__io_1_1Channel.html#a0c00bab2dad604dde176c4190553915c">.start_and_poll()</a>.</li>
</ul>
<p >As this returns, in-traffic may be received and emitted to your handlers (or the special-case blocking op <code>.sync_request()</code> which is unavailable with the <code>sync_io</code>-pattern variant). (These handlers can be registered &ndash; after <em>or before</em> the start method &ndash; via <code>expect_*()</code>, <code>async_request()</code>, <code>set_*unexpected_response_handler()</code>. Un-register via <code>undo_*()</code> and <code>unset_*()</code>.)</p>
<p >The idea of calling a start method is presumably simple enough, but a key input to that method is the <b>on-error handler</b> function you'll need to supply. That guy in and of itself is straightforward enough: it takes a <code>const Error_code&amp;</code>, and Flow-IPC shall set this to some truthy value indicating the error that occurred. However the topic of errors is somewhat subtle. Let's discuss.</p>
<h3>Errors</h3>
<p >One class of error we should get out of the way is the <b>non-fatal a/k/a non-channel-hosing error</b> type. As of this writing there is only one: <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297abcfca4c2347f9d377dd2ac41c41dc027" title="A (usually user-specified) timeout period has elapsed before a blocking operation completed.">ipc::transport::error::Code::S_TIMEOUT</a>; it is emitted by <code>.sync_request()</code> if and only if the one expected response does not arrive within the (optional) timeout value given to the method. This is considered a user error, and it does not have any ill consequences as far as Flow-IPC is concerned. (You are of course free to explode everything, if it is appropriate.) If other such error eventualities arise over time, they are documented explicitly. So from this point forward we only discuss <b>fatal a/k/a channel-hosing errors</b>.</p>
<p >The main principle &ndash; and one that happens to also apply to various other objects in the library, including <a class="el" href="classipc_1_1session_1_1Session.html" title="A documentation-only concept defining the local side of an IPC conversation (session) with another en...">ipc::session::Session</a>, <a class="el" href="classipc_1_1session_1_1Session__server.html" title="To be instantiated typically once in a given process, an object of this type asynchronously listens f...">ipc::session::Session_server</a> et al, and <a class="el" href="namespaceipc_1_1transport.html" title="Flow-IPC module providing transmission of structured messages and/or low-level blobs (and more) betwe...">ipc::transport</a> core-layer senders/receivers &ndash; is as follows:</p>
<p ><em>A channel-hosing error occurs at most once per <code>struc::Channel</code> object.</em></p>
<p >Moreover, for <code>struc::Channel</code> specifically:</p>
<p ><em>A channel-hosing error is emitted to the user at most once per <code>struc::Channel</code> object.</em> Once it has been emitted, it will not be emitted again.</p>
<p >How is it emitted? Answer:</p><ul>
<li>If triggered synchronously by an outgoing-op (namely <code>.send()</code>, <code>.async_request()</code>, <code>.sync_request()</code>), then it shall be synchronously emitted by that method call. It is your responsibility to be ready for an error emission.<ul>
<li>Here we follow the <code>flow::error</code> error emission semantics (themselves inspired by boost.asio albeit a more compact version that reduces the number of method overload signatures by ~50%). The method takes an arg <code>Error_code* err_code</code>.<ul>
<li>If you pass-in null: The method will <em>not throw</em> if no error is emitted; else will <em>throw</em> <code>flow::error::Runtime_error</code> exception with <code>.code()</code> returning the specific truthy <code>Error_code</code> being emitted.</li>
<li>If you pass-in non-null: The method will set <code>*err_code</code> to falsy if no error is emitted; else to truthy <code>Error_code</code> being emitted.</li>
</ul>
</li>
</ul>
</li>
<li>If triggered by an incoming-op, which can only occur asynchronously, then it shall be asynchronously emitted to the <b>on-error handler</b> you have supplied to <code>.start()</code> (or <code>sync_io</code>-pattern counterpart, <code>.start_and_poll()</code>). It is your responsibility to take the proper steps inside this on-error handler.</li>
</ul>
<p >This is an important dichotomy to understand. There's at most one occurrence of a channel-hosing error being emitted, and if it does occur, it will occur through exactly one of the above ways. Either a send method will emit is synchronously, or some incoming-direction processing (occurring concurrently in the background with async-I/O pattern, or inside <code>(*on_active_ev_func)()</code> or <code>.start_and_poll()</code> itself with <code>sync_io</code> pattern) will emit it to the on-error handler. Either way you must be ready for it.</p>
<p >What happens to a hosed channel? Rest easy: You can still call its APIs; they will not crash/abort/lead to undefined behavior. They will basically do nothing. In particular most &ndash; including <code>.expect_*()</code>, <code>.send()</code>, <code>.async_request()</code> &ndash; will return <code>false</code>. One, <code>.sync_request()</code>, will return null pointer (instead of the resulting response message pointer) while setting <code>*err_code</code> to falsy (nominally success) (or not throwing if <code>err_code</code> is null). It is guaranteed, also, that no handler (except that given to <code>.async_end_sending()</code>; see next section) will possibly be called after the channel-hosing error is emitted.</p>
<p >The more salient question is, perhaps, what <em>should</em> you do once you've detected a channel-hosing error (again, either via <code>.send()</code> et al synchronously, or via on-error handler)? Answer: You should stop using the channel; instead you should destroy it (see next section of this page).</p>
<p >You might be thinking to yourself: Well, that's no problem. Channel hosed? Don't use the channel; destroy it sometime soon just to free resources. Indeed. However there <em>is</em> a subtlety albeit applicable only in async-I/O-pattern <code>struc::Channel</code>. It is this:</p>
<p >The channel might get hosed <em>at any time</em>. Consider this code:</p>
<div class="fragment"><div class="line"><span class="comment">// Receiver side: Your async-I/O loop&#39;s main thread W.</span></div>
<div class="line"> </div>
<div class="line">cool_channel.start([<span class="keyword">this</span>](<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a>&amp; err_code)</div>
<div class="line">{</div>
<div class="line">  <span class="comment">// We are unspecified thread (async-I/O pattern).  Offload true handling back onto your thread W.</span></div>
<div class="line">  post([<span class="keyword">this</span>, err_code]()</div>
<div class="line">  {</div>
<div class="line">    <span class="comment">// --&gt; DISCUSSION POINT Y. &lt;--</span></div>
<div class="line">    teardown(err_code);</div>
<div class="line">  });</div>
<div class="line">}); <span class="comment">// cool_channel.start()</span></div>
<div class="line"> </div>
<div class="line"><span class="keyword">const</span> <span class="keywordtype">bool</span> ok = cool_channel.expect_msg(Cool_structured_channel::Msg_which::SUM_REQUEST,</div>
<div class="line">                                        [<span class="keyword">this</span>](Cool_structured_channel::Msg_in_ptr&amp;&amp; req)</div>
<div class="line">{</div>
<div class="line">  <span class="comment">// We are unspecified thread (async-I/O pattern).  Offload true handling back onto your thread W.</span></div>
<div class="line">  post([<span class="keyword">this</span>,</div>
<div class="line">        req = std::move(req)]()</div>
<div class="line">  {</div>
<div class="line">    <span class="comment">// We are back in: Your async-I/O loop&#39;s main thread W.</span></div>
<div class="line"> </div>
<div class="line">    <span class="comment">// --&gt; DISCUSSION POINT A. &lt;--</span></div>
<div class="line"> </div>
<div class="line">    int64_t sum = 0;</div>
<div class="line">    <span class="keyword">const</span> <span class="keyword">auto</span> sum_func = [&amp;](int64_t val) { sum += val; };</div>
<div class="line">    <span class="keyword">auto</span> root = req-&gt;body_root().getSumRequest();</div>
<div class="line">    <span class="keyword">auto</span> list = root.getTermsToAdd();</div>
<div class="line">    std::for_each(list.begin(), list.end(), sum_func);</div>
<div class="line">    sum *= root.getConstantFactor();</div>
<div class="line"> </div>
<div class="line">    <span class="keyword">auto</span> msg = cool_channel.create_msg();</div>
<div class="line">    msg.body_root()-&gt;initSumResponse().setResult(sum);</div>
<div class="line">    msg.body_root()-&gt;setDescription(<span class="stringliteral">&quot;the sum you ordered, sir&quot;</span>);</div>
<div class="line"> </div>
<div class="line">    <span class="comment">// --&gt; DISCUSSION POINT B. &lt;--</span></div>
<div class="line"> </div>
<div class="line">    <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a> err_code;</div>
<div class="line">    <span class="keyword">const</span> <span class="keywordtype">bool</span> ok = msg.send(msg,</div>
<div class="line">                             req.get(),</div>
<div class="line">                             &amp;err_code); <span class="comment">// Let&#39;s not omit, so we need not catch exception on error.</span></div>
<div class="line">    <span class="comment">// --&gt; DISCUSSION POINT C. &lt;--</span></div>
<div class="line"> </div>
<div class="line">    <span class="keywordflow">if</span> (err_code)</div>
<div class="line">    {</div>
<div class="line">      assert(ok); <span class="comment">// A new error being emitted &lt;=&gt; ok == true.  `ok == false` means channel is already unusable, no new error emitted.</span></div>
<div class="line">      teardown(err_code);</div>
<div class="line">    }</div>
<div class="line">  }); <span class="comment">// post()</span></div>
<div class="line">}); <span class="comment">// cool_channel.async_request()</span></div>
<div class="line"> </div>
<div class="line"><span class="comment">// --&gt; DISCUSSION POINT X. &lt;--</span></div>
<div class="line"> </div>
<div class="line"><span class="comment">// ...</span></div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">void</span> teardown(<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">Error_code</a>&amp; err_code)</div>
<div class="line">{</div>
<div class="line">  FLOW_LOG_INFO(<span class="stringliteral">&quot;Channel hosed for reason [&quot;</span> &lt;&lt; err_code &lt;&lt; <span class="stringliteral">&quot;] [&quot;</span> &lt;&lt; err_code.message() &lt;&lt; <span class="stringliteral">&quot;].  Shutting down.&quot;</span>);</div>
<div class="line"> </div>
<div class="line">  <span class="comment">// ...Destroy channel.  See next section of Manual....</span></div>
<div class="line">}</div>
<div class="ttc" id="anamespaceipc_html_aa3192e586cc45d3e7c22463bf2760f89"><div class="ttname"><a href="namespaceipc.html#aa3192e586cc45d3e7c22463bf2760f89">ipc::Error_code</a></div><div class="ttdeci">flow::Error_code Error_code</div><div class="ttdoc">Short-hand for flow::Error_code which is very common.</div><div class="ttdef"><b>Definition:</b> <a href="common_8hpp_source.html#l00298">common.hpp:298</a></div></div>
</div><!-- fragment --><p >Chronologically:</p><ol type="1">
<li>Point X: We've called <code>.expect_msg()</code>. Say it returned <code>true</code> which means the channel is <em>not</em> hosed at that exact point in time. It, itself, lacks an <code>err_code</code> arg in its signature, so it cannot itself emit a new error.</li>
<li>Point A: Apparently a message has arrived. So at that exact point the channel is <em>not</em> hosed either. Even if it is, <code>.create_msg()</code> has nothing to do with transmitting anything, and certainyl all the message-reading and -filling logic is orthogonal to the channel itself. No problem.</li>
<li>Point B: Here we <code>.send()</code>. That's a transmission-related API, and moreover it can itself emit a (new) error. Anyway, we don't know if the channel is hosed or not per se, and there's only one way to find out: call it.</li>
<li>Point C: Now there are 2 error-related outputs: <code>ok</code> (return value) and <code>err_code</code> (out-arg). (We could have passed-in null or omitted arg &ndash; same thing &ndash; in which case we'd need to be ready to catch resulting exception.)<ul>
<li>Suppose <code>ok == true</code>, but <code>err_code</code> is truthy. That would indicate <em>new channel-hosing error</em> being emitted. Hence we call <code>teardown()</code> which will stop work on this channel &ndash; deinitialize whatever, etc.</li>
<li>Suppose <code>ok == false</code>. What does it mean? Answer: Something came into the channel <em>in the background concurrently</em> between the start of our in-message handler (when everything was OK) and the point where we decided to send the response. So what should we do? It depends. Informally speaking:<ul>
<li>If we wouldn't be doing anything further in the handler anyway, then just don't. One could simply ignore <code>ok</code>. Flow-IPC would log sufficiently; trust me.</li>
<li>However, if there were more logic at that point beyond what is shown in this example, then we might check for <code>ok == false</code> and return before doing anything else. After all the channel is hosed. <em>In fact this means, with 100% certainty, that the code at Point Y will execute soon.</em> We might as well put all the deinit stuff we want to do, there.</li>
</ul>
</li>
</ul>
</li>
<li>Point Y: Suppose, indeed, <code>.send()</code> returned <code>ok == false</code>. Then this code shall ASAP. Presumably something happened on the channel's background in-traffic processing that constitutes the channel being hosed. Usually it's a graceful-close or <code>EPIPE</code> or the like. So we call <code>teardown()</code>, where we centrally handle the deinit of the channel.</li>
</ol>
<p >If one is used to progamming in this async-I/O model &ndash; most commonly in our world using boost.asio &ndash; this will be familiar. It is a little odd to think of flow control this way at first, but one gets used to it. There are certainly major positives, but this "inverted flow control" could be considered a negative (which people fight in various ways &ndash; e.g. by using micro-threads/fibers, though that has its own complexity costs).</p>
<p >That said, if you're using <code>sync_io</code>-pattern <code>struc::Channel</code>, these considerations go away. Nothing happens concurrently in the background, unless your own code makes it so. Yes, there is still the on-error handler; yes, <code>.send()</code> can still emit an error &ndash; or return <code>false</code>. However there is no need to worry about the channel being fine at Point A but at Point C <code>.send()</code> returning <code>false</code>. One would "just" not get to Point B, if earlier your own on-async-wait call <code>(*on_active_ev_func)()</code> triggered the on-error handler (synchronously). Flow control becomes linear, and things don't happen suddenly in the background. Hence properly written code should be able to <code>assert(ok)</code> at Point C without fear.</p>
<p >At any rate, with the async-I/O pattern, the above gives a pretty good idea of how to structure error handling and the associated flow control. Basically:</p><ul>
<li>Centralize handling channel-hosing errors in a function like <code>teardown()</code>, called either from on-error handler or upon detecting truthy <code>Error_code</code> from a send-op.</li>
<li>Be ready for various APIs to return <code>false</code> (null + no-error-emission in case of <code>.sync_request()</code>) and possibly short-circuit further logic in that case.</li>
</ul>
<h3>Destroying <code>struc::Channel</code></h3>
<p >Here we will keep it simple and just give you a recipe to follow. Whether done with the <code>struc::Channel</code> without any error, or <em>due to</em> a channel-hosing error, do the following. These steps could be in <code>teardown()</code> in the preceding example code snippet.</p>
<p >First: Invoke <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a" title="Operating at the unstructured layer, executes a graceful-close send by forwarding to the async transp...">ipc::transport::struc::Channel::async_end_sending()</a>. Give it a completion handler <code>F()</code>.</p>
<p >Second: In <code>F()</code>, or after <code>F()</code>, destroy the <code>struc::Channel</code> to free resources. (The <code>Error_code</code> passed to <code>F()</code> is not particularly important &ndash; you can/should log it, of course, but that's about it.)</p>
<p >That's it. (In the <code>sync_io</code>-pattern variation of <code>.async_end_sending()</code>, same deal; except that it might (in fact usually will) complete synchronously instead of invoking <code>F()</code>. So handle that synchronously, if it happens.)</p>
<dl class="section note"><dt>Note</dt><dd>We didn't explain why here. See <a class="el" href="classipc_1_1transport_1_1struc_1_1Channel.html#ab08057edd9832d94ea0e18a17c42200a">.async_end_sending()</a> doc header if interested. Short version: If no error, this will ensure any internally queued-due-to-would-block outgoing traffic (which is unlikely but possible to exist) will get flushed out before you destroy the channel. That could make things run smoother on the opposing side. And if an error does occur or has occurred, it'll just complete immediately &ndash; no harm done.</dd>
<dd>
What if you don't do this and just destroy the <code>struc::Channel</code>? The aforementioned doc header answers that too. Short version: In many cases it's probably fine. However, if the transport out-direction happens to be in would-block state at this time, the opposing side might miss some of the stuff you intended it to receive &ndash; hard to say whether that's important or not; depends on your application/protocol's design. So all-in-all it's better to flush outgoing payloads instead of leaving it to chance. This is no different conceptually from properly closing a TCP connection; but truthfully with IPC there's ~zero latency and zero loss, so fewer bad things realistically happen in practice. Still &ndash; best to code defensively.</dd>
<dd>
Last thing (applies to async-I/O pattern only, not <code>sync_io</code>): <code>.async_end_sending()</code> is a <code>Channel</code>-level operation (as opposed to the higher <code>struc::Channel</code> layer). Its completion handler <em>will</em> execute, even if you don't wait for that to occur and destroy <code>struc::Channel</code> first. In that case the destructor will invoke it with an operation-aborted code. If you follow the above recipe, then that won't happen, but defensively-written code should nevertheless do something close to the following in <code>F()</code>: <code>if (err_code == <a class="el" href="namespaceipc_1_1transport_1_1error.html#adfef15ef4e76cc55d652fbd9c2797297afe29343445a7bf167cc186a44bd2c6ed" title="Async completion handler is being called prematurely, because underlying object is shutting down,...">ipc::transport::error::Code::S_OBJECT_SHUTDOWN_ABORTED_COMPLETION_HANDLER</a>) { return; }</code>.</dd></dl>
<p>The next page is: <a class="el" href="chan_struct_advanced.html">Structured Message Transport: Messages As Long-lived Data Structures / Advanced Topics</a>.</p>
<hr  />
<center><b>MANUAL NAVIGATION:</b> <a class="el" href="universes.html">Preceding Page</a> - <a class="el" href="chan_struct_advanced.html">Next Page</a> - <a href="./pages.html"><b>Table of Contents</b></a> - <a class="el" href="namespaceipc.html"><b>Reference</b></a></center> </div></div><!-- contents -->
</div><!-- PageDoc -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 11 2025 20:02:26 for Flow-IPC by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.4
</small></address>
</body>
</html>
